package com.sentiment.crawler;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.jsoup.nodes.Document;

import com.sentiment.config.Config;
import com.sentiment.contentextractor.ContentExtractor;
import com.sentiment.contentextractor.News;
import com.sentiment.db.CrawlingPageDB;
import com.sentiment.db.RalationMapDB;
import com.sentiment.db.TextDB;
import com.sentiment.obj.CrawlingPage;
import com.sentiment.obj.RalationMap;
import com.sentiment.obj.Text;
import com.sentiment.strategy.IdGenerator;
import com.sentiment.strategy.TitleFilter;
import com.sentiment.tools.StringTools;
import com.sentiment.webcollector.crawler.DeepCrawler;
import com.sentiment.webcollector.model.Links;
import com.sentiment.webcollector.model.Page;

/**
 * 爬取百度搜索的搜索结果 分页爬取百度 并下载搜索结果中的每个网页到本地
 * 
 * @author wjk
 *
 */

public class BaiduCrawler extends DeepCrawler {
	private List<CrawlingPage> li = new ArrayList<CrawlingPage>();
	private Logger logger = Config.getLogger(this.getClass());
	// 用于记录原文章标题
	private String srcId = "";

	public BaiduCrawler(String crawlPath, String srcId) {
		super(crawlPath);
		this.srcId = srcId;
	}

	/**
	 * 覆写了原有方法从页面中获取下一层爬取的链接
	 */
	@Override
	public Links visitAndGetNextLinks(Page page) {
		String url = page.getUrl();
		// 如果是百度的页面
		if (Pattern.matches("https://www.baidu.com/s\\?wd=.*", url)) {
			Links nextLinks = new Links();
			// 将所有搜索结果条目的超链接返回，爬虫会在下一层爬取中爬取这些链接
			// 此处第二个参数为选择器语法（详见）：http://www.open-open.com/jsoup/selector-syntax.htm
			nextLinks.addAllFromDocument(page.getDoc(), "h3>a[data-click]");
			return nextLinks;
		} else {
			try {
				String title = getTitle(page);
				String tarId = IdGenerator.generateTarId();
				CrawlingPage cp = new CrawlingPage(srcId, tarId, url, title);
				li.add(cp);
			} catch (Exception e) {
				logger.error(e);
			}
		}
		return null;
	}

	/**
	 * 往百度搜索引擎中加入关键字并爬取搜索结果页面 保存每条搜索记录到数据库中
	 * 
	 * @param keyword
	 *            待搜索的关键字
	 * @param title
	 *            该参数的目的是为了获取srcId
	 */
	public void getSearch(String keyword) {
		CrawlingPageDB cpdb = new CrawlingPageDB();
		try {
			addSeed("https://www.baidu.com/s?wd=" + URLEncoder.encode(keyword, "utf-8"));
			// 遍历中第一层爬取百度的搜索结果页面，
			// 第二层爬取搜索结果对应的页面，所以这里要将层数设置为2
			start(2);
			for (CrawlingPage cp : li) {
				// 将页面编码信息、URL地址、文件名等存储进数据库
				cpdb.insertData(cp);
			}
			cpdb.DBClose();
		} catch (Exception e) {
			logger.error(e);
		}
	}

	/**
	 * 从html页面中获取title标签
	 * 
	 * @param page
	 *            Page对象 具体见WebCollector
	 * @return 返回title标签的text内容
	 */
	private String getTitle(Page page) {
		Document doc = page.getDoc();
		String title = doc.title();
		// 对标题进行处理
		// For example, given HTML <p>Hello <b>there</b> now!</p>, p.text()
		// returns "Hello there now!"
		title = StringTools.deleteNbspAndBlank(title);

		return title;
	}

	/**
	 * 建立关系源文和爬取文映射 并将其存入数据库中 根据id
	 * 
	 */
	public void createRalationMap() {
		CrawlingPageDB cpdb = new CrawlingPageDB();
		//
		List<CrawlingPage> cpli = cpdb.findAllDataByKeyAndVal("bySrc", srcId);
		cpdb.DBClose();
		ArrayList<String> tarIdAll = new ArrayList<String>();
		for (int i = 0; i < cpli.size(); i++) {
			tarIdAll.add(cpli.get(i).getId());
		}

		RalationMap rm = new RalationMap(srcId, tarIdAll, cpli.size());
		RalationMapDB rmdb = new RalationMapDB();
		rmdb.insertData(rm);
		rmdb.DBClose();
	}

	/**
	 * 针对所有应该爬取的url的解析 使用WebCollector的正文解析工具
	 */
	public void parserAllHtml() {
		RalationMapDB rmdb = new RalationMapDB();
		RalationMap rm = rmdb.findDataByKeyAndVal("srcId", srcId);
		rmdb.DBClose();
		List<String> tarIdAll = rm.getTarIdAll();
		CrawlingPageDB cpdb = new CrawlingPageDB();
		TextDB tdb = new TextDB();
		for (int i = 0; i < rm.getTarAmount(); i++) {
			CrawlingPage cp = cpdb.findDataByKeyAndVal("id", tarIdAll.get(i));
			if (cp == null) {
				logger.error("-----未找到该对应页面 放弃处理-----");
				continue;
			} else if (TitleFilter.filter(cp.getTitle())) {
				logger.error("-----在配置文件中有该标题信息-----请检查titleFilter.xml配置文件-----");
				logger.error("-----说明该标题是处于过滤状态　即还没对该标题采取合适的正文提取方案-----");
				continue;
			}
			try {
				News news = ContentExtractor.getNewsByUrl(cp.getUrl());
				// 将处理后的文章保存到数据库中
				Text tx = new Text(cp.getTitle(), news.getContent(), cp.getId(), getWriter(), news.getTime());
				tdb.insertData(tx);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				logger.error(e);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				logger.error(e);
			}
		}
		tdb.DBClose();
		cpdb.DBClose();
	}

	private boolean deleteFile(File file) {
		if (file.exists()) { // 判断文件是否存在
			if (file.isFile()) { // 判断是否是文件
				return file.delete();
			} else if (file.isDirectory()) { // 否则如果它是一个目录
				File files[] = file.listFiles(); // 声明目录下所有的文件 files[];
				for (int i = 0; i < files.length; i++) {
					deleteFile(files[i]);
				}
			}
			return file.delete();
		}
		return false;
	}

	private String getWriter() {
		return "null";
	}

}